package io.github.yotta.export.core.provider;

import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author yotta
 * @date 2025/4/27
 */
@Slf4j
public class MinioFileProvider implements FileProvider {
    private final MinioFileProviderProperties minioProperties;
    private final MinioClient minioClient;

    public MinioFileProvider(MinioFileProviderProperties minioProperties) {
        this.minioProperties = minioProperties;
        // 初始化 MinIO 客户端
        this.minioClient = MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }


    @Override
    public String generateFilePath(String fileName, String ext) {
        return Paths.get(
                minioProperties.getBaseDir(),                // 父目录
                fileName,
                LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_FORMAT)),  // 时间归组
                fileName + ext
        ).toString().replace("\\", "/"); // windows 下路径分隔符为反斜杠，需要替换为正斜杠
    }

    @Override
    public void saveFile(String filePath, File file) throws IOException {
        // 从 File 对象获取输入流
        InputStream inputStream = Files.newInputStream(file.toPath());
        long length = file.length();
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket(minioProperties.getBucketName())
                // 此为对象名称，即文件在 MinIO 存储桶中的名称。它可以包含路径信息，类似于文件系统中的文件路径，这样能对文件进行更细致的组织。
                .object(filePath)
                .stream(inputStream, length, -1).build();
        try {
            minioClient.putObject(putObjectArgs);
        } catch (Exception e) {
            log.error("save file to minio fail by {}", e.getMessage(), e);
            throw new IOException(e);
        }
    }

    public String getFileUrl(String filePath) {
        // 生成预签名 URL，设置有效期为 1 小时
        String presignedUrl = null;
        try {
            presignedUrl = minioClient.getPresignedObjectUrl(
                    io.minio.GetPresignedObjectUrlArgs.builder()
                            .method(io.minio.http.Method.GET)
                            .bucket(minioProperties.getBucketName())
                            .object(filePath)
                            .build());
        } catch (Exception e) {
            log.error("get file url from minio fail by {}", e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return presignedUrl;
    }

    @Override
    public InputStream openFile(String filePath) throws IOException {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(minioProperties.getBucketName())
                .object(filePath)
                .build();
        try {
            return minioClient.getObject(getObjectArgs);
        } catch (Exception e) {
            log.error("open file to minio fail by {}", e.getMessage(), e);
            throw new IOException(e);
        }
    }
}
